/*
 Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
 Original sources are available at www.latestbit.com

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

 CommandProcessor.hpp. Created on: 22.09.2009 15:22:51 
 */

#ifndef COMMANDPROCESSOR_HPP_
#define COMMANDPROCESSOR_HPP_

#include "smartobjects/SmartObjectsDefs.hpp"
#include "smartobjects/core/ICommandProcessor.hpp"
#include "smartobjects/core/DefaultCommandProcessorHandler.hpp"

namespace smartobjects {

class CommandProcessor : public ICommandProcessor {
public:
	SO_DLLPRFX CommandProcessor(ISmartBus* poBus);
	SO_DLLPRFX virtual ~CommandProcessor();

	SO_DLLPRFX virtual void sendAsyncRequest(
			ConnectionHandler* poConnectionHandler,
			INetworkCommand* poRequest,
			ICommandProcessorHandler* poHandler,
			RefObject* poUserObject,
			unsigned int nTimeoutInSec);

	SO_DLLPRFX virtual INetworkCommand* sendSyncRequest(
			ConnectionHandler* poConnectionHandler,
			INetworkCommand* poRequest,
			unsigned int nTimeoutInSec);

	SO_DLLPRFX virtual void sendResponse(
			ConnectionHandler* poConnectionHandler,
			INetworkCommand* poResponse);

	SO_DLLPRFX virtual void addRequestHandler (
			ICommandProcessorHandler* poHandler,
			const std::string& sDestinationFilter );

	SO_DLLPRFX virtual void addRequestHandler (
			ICommandProcessorHandler* poHandler,
			const std::string& sDestinationFilter,
			const std::string& sInstanceIdFilter );

	SO_DLLPRFX virtual void addRequestHandler (
			ICommandProcessorHandler* poHandler,
			IServerSkeleton* poSmartObject);

	SO_DLLPRFX virtual void delRequestHandler (
			ICommandProcessorHandler* poHandler );

	SO_DLLPRFX virtual unsigned int getAsyncCallsQueueSize();

	SO_DLLPRFX virtual void onReceived(ConnectionHandler* poHandler, ByteBuffer* poBuffer) throw();
	SO_DLLPRFX virtual void onReceiveError(ConnectionHandler* poHandler, const std::string& sErrorMessage) throw();
	SO_DLLPRFX virtual void onWriteError(ConnectionHandler* poHandler, const std::string& sErrorMessage) throw();


protected:

	#include "CommandProcessorAsyncQueueItem.inl"

	SO_DLLPRFX virtual void onAsyncCallHandleTimeout(Timer::TimerId nTimerId);
	SO_DLLPRFX virtual void onReceivedRequest(ConnectionHandler* poHandler, INetworkCommand* poRequest);
	SO_DLLPRFX virtual void onReceivedResponse(ConnectionHandler* poHandler, INetworkCommand* poResponse);

	SO_DLLPRFX virtual void reuseRequestBuffer(INetworkCommand* poRequest, INetworkCommand* poResponse);
	SO_DLLPRFX virtual void returnBufferToCache(INetworkCommand* poCommand);
	SO_DLLPRFX virtual ByteBuffer* getBufferFromCache(unsigned int nInitSize);

	SO_DLLPRFX virtual void sendAsyncRequest(
			ConnectionHandler* poConnectionHandler,
			INetworkCommand* poRequest,
			ICommandProcessorHandler* poHandler,
			RefObject* poUserObject,
			unsigned int nTimeoutInSec,
			SyncCallContext* poSyncCallContext);

	SO_DLLPRFX virtual void releaseAsyncCalls();
	SO_DLLPRFX virtual void releaseBuffers();

protected:
	ISmartBus* m_poBus;

	// typedef boost::unordered_map < std::string, ICommandProcessorHandler* > CommandHandlerFilters;
	typedef boost::bimap < boost::bimaps::unordered_set_of<std::string>, boost::bimaps::unordered_multiset_of < ICommandProcessorHandler* > > CommandHandlerFilters;
	CommandHandlerFilters m_mHandlersByDest;
	CommandHandlerFilters m_mHandlersByInstanceId;
	boost::shared_mutex m_mxFilters;

	Timer* m_poAsyncCallsTimer;

	typedef boost::unordered_map < Timer::TimerId, AsyncCallQueueItem > AsyncCallsMap;
	AsyncCallsMap m_mAsyncCalls;
	boost::recursive_mutex m_mxAsyncCalls;

	typedef std::list<ByteBuffer*> BuffersCache;
	BuffersCache m_aBuffersCache;
	boost::recursive_mutex m_mxBuffersCache;

	boost::thread_specific_ptr<RefObject> m_poTlsSyncContext;
	DefaultCommandProcessorHandler* m_poDefaultProcessorHandler;
};

}

#endif /* COMMANDPROCESSOR_HPP_ */
